package leetcodev1.链表;

public class LeetCode92 {

    //如果是数组直接执行swap就好了
    //1.长度为n的栈，然后依次取出
    //2.修改版的链表翻转3个节点关键left-1 left right+1
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode index = head, pre = null, leftIndex = null, rightIndex = null, last = null;
        while (index != null) {
            if (left == 1) {
                pre = index;
            } else if (left == 0) {
                leftIndex = index;
            } else if (right == 0) {
                rightIndex = index;
            }

            left--;
            right--;
            index = index.next;
        }
        last = rightIndex.next;
        index = leftIndex.next;
        while (index != null) {
            ListNode tmp = index.next;
            index.next = leftIndex;//头插
            leftIndex = index;//重置头结点
            index = tmp;//移动下标
        }
        pre.next.next = last;
        pre.next = leftIndex;
        return head;
    }
}

class Answer92{
    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 因为头节点有可能发生变化，使用虚拟头节点可以避免复杂的分类讨论
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;

        ListNode pre = dummyNode;
        // 第 1 步：从虚拟头节点走 left - 1 步，来到 left 节点的前一个节点
        // 建议写在 for 循环里，语义清晰
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;//获取前驱节点
        }

        // 第 2 步：从 pre 再走 right - left + 1 步，来到 right 节点
        ListNode rightNode = pre;
        for (int i = 0; i < right - left + 1; i++) {
            rightNode = rightNode.next;//后继节点
        }

        // 第 3 步：切断出一个子链表（截取链表）
        ListNode leftNode = pre.next;
        ListNode curr = rightNode.next;

        // 注意：切断链接
        pre.next = null;
        rightNode.next = null;

        // 第 4 步：同第 206 题，反转链表的子区间
        reverseLinkedList(leftNode);//新链表

        // 第 5 步：接回到原来的链表中
        pre.next = rightNode;//翻转完成
        leftNode.next = curr;//拼接
        return dummyNode.next;
    }

    //翻转链表
    private void reverseLinkedList(ListNode head) {
        // 也可以使用递归反转一个链表
        ListNode pre = null;
        ListNode cur = head;

        while (cur != null) {
            ListNode next = cur.next;
            cur.next = pre;//头插法
            pre = cur;//重置头部
            cur = next;//移动小标
        }
    }

}
